iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
AI & Data

文理組人都能上手的入門 NLP(自然語言處理)系列 第 20

[Day 19] 監督式機器學習模型:誰芭比Q了嗎?-實作羅吉斯迴歸(Logistic Regression) & TF-IDF

  • 分享至 

  • xImage
  •  

  大家午安,昨天介紹過羅吉斯迴歸的原理之後,今天要帶大家實作羅吉斯迴歸的模型,任務是要偵測推特上的貼文是否有憂鬱傾向。在NLP的領域裡面,我們把這種分析文本情感傾向的任務稱作「文本情感分析(sentiment analysis)」。偵測貼文是否具有憂鬱或自傷傾向也是現在對社群媒體運營者來說很重要的事情,相信大家應該都有聽說過FB跟IG會偵測你的貼文然後給予關心的事情。雖然做文本情感分析的方法有很多,但我們今天還是以比較基礎的特徵-TF-IDF來訓練模型,也順便把之前沒示範到的實作補起來。

TF-IDF

  先把資料讀到colab裡面。讀進來看之後你就會發現這個資料每一行的名稱也太長了吧,操作起來不是很方便,所以我們就幫他換幾個比較方便的名字吧。(順便複習一下pandas的使用)

import pandas as pd
raw_data = pd.read_csv("/content/sentiment_tweets.csv")
raw_data.columns = ["index", "tweet", "label"]

  今天一樣使用scikit learn提供的工具來進行特徵萃取。因為最簡單的TF-IDF說白了就是在詞頻的基礎上多加了逆向文檔頻率的計算,實際使用scikit learn操作的時候跟詞袋模型的萃取基本上沒什麼差異。我們一樣要把資料裡面的文本轉換成向量化工具可以讀懂的樣子。在初始化向量化工具之後就可以把轉換過的資料丟進去給他計算TF-IDF的值了。

raw_text = []
for rows in range(len(raw_data["tweet"])):
    text = raw_data.at[rows, "tweet"]
    raw_text.append(text)

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
vectorized_data = vectorizer.fit_transform(raw_text)

  這個工具跟BOW不一樣的地方在於他多了一個可以讓我們看的IDF資料:

print(vectorizer.idf_[0:5])
# 輸出
[7.93876933 8.29544428 9.54820724 9.54820724 9.54820724]

  接下來就跟詞袋模型一樣,我們把資料裡面的type取出來作為標記資料的行名,再跟計算結果統合成一個表示特徵的dataframe。

feature_arr = vectorizer.get_feature_names_out()
feature_data = vectorizer.transform(raw_text)
annotation = feature_data.toarray()

feature_df = pd.DataFrame(annotation, columns=[feature_arr])
label_df = raw_data[["label"]]

羅吉斯迴歸(Logistic Regression)

區分訓練集(traing set)&測試集(test set)

  資料的前處理完成之後,我們就可以開始訓練模型了,這邊開始因為scikit learn基本上都已經幫我們寫好工具了,跟Naive Bayes的進行都是大同小異的。

from sklearn.model_selection import train_test_split
data_train, data_test, label_train, label_test = train_test_split(feature_df, label_df, test_size=0.2, random_state=88)

模型訓練

  我們一樣把Logistic Regression的套件引進來之後出使用模型,然後再把訓練集的標記資料跟正確答案丟給模型。

from sklearn.linear_model import LogisticRegression
model = LogisticRegression().fit(data_train, label_train)

模型評估

  這邊開始跟Naive Bayes的差異在於,因為Logistic Regression公式求出來的是它分屬不同類別的機率,所以除了預測結果之外,我們還可以看到準確的機率數字。

label_predict = model.predict(data_test)
print(label_predict[0:10])
label_predict_probability = model.predict_proba(data_test)
print(label_predict_probability[0:10])
# 輸出
[0 0 0 0 0 0 0 0 0 0]
[[0.94254135 0.05745865]
 [0.9721023  0.0278977 ]
 [0.9654564  0.0345436 ]
 [0.9600599  0.0399401 ]
 [0.96620099 0.03379901]
 [0.93570204 0.06429796]
 [0.95370278 0.04629722]
 [0.94124656 0.05875344]
 [0.95658776 0.04341224]
 [0.91855423 0.08144577]]

  從上面我們可以看到,測試集的前10筆資料都被預測為沒有憂鬱傾向的發文,還有這些發文屬於非憂鬱傾向的機率跟屬於憂鬱傾向的機率。最後當然還是要拿來跟正確答案比較一下,評估這個模型的表現囉~

from sklearn.metrics import confusion_matrix, precision_recall_fscore_support
 
print(confusion_matrix(label_test, label_predict))
evaluation = precision_recall_fscore_support(label_test, label_predict, average='macro')
accuracy = model.score(data_test, label_test)
print("accuracy: " + str(accuracy) + "\nprecision: " + str(evaluation[0]) + "\nrecall: " + str(evaluation[1]) + "\nfscore: " + str(evaluation[2]))
# 輸出
[[1605    0]
 [  44  414]]
 
accuracy: 0.98
precision: 0.99
recall: 0.95
fscore: 0.97

  結果看起來也是非常好呢,大概是因為這邊提供的資料是比較漂亮,沒那麼多奇奇怪怪的網路用語,再加上有憂鬱傾向的文本比較少,他們的特徵如果相似的話就會顯得特別明顯。但這並不代表真實生活中再進行分類任務的時候也可以這麼美好,之後有機會再寫一篇文針對情感分析的難點做介紹。那麼今天就到這邊結束了,大家明天見~


參考資料

scikit learn


上一篇
[Day 18] 監督式機器學習模型:身世之謎與自我追尋-羅吉斯迴歸(Logistic Regression)
下一篇
[Day 20] 監督式機器學習模型:找那個逃跑空間最大的地方龜就對了!-支持向量機(Support Vector Machine)
系列文
文理組人都能上手的入門 NLP(自然語言處理)31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言